package com.key.puzzlemodel.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;

import com.key.puzzlemodel.R;
import com.key.puzzlemodel.bean.HVPuzzleBean;

public class PartImageView extends AppCompatImageView {

    private Bitmap mBitmap;// 要显示的Bitmap
    private RectF mPartRectF;// 要显示Bitmap的指定区域
    private Matrix mMatrix;// 控制Bitmap缩放、位移等

    private Paint mPaint;
    private PorterDuffXfermode mPorterDuffXfermode;

    /**
     * 0, 宽度固定，高度可变
     * 1, 高度固定，宽度可变
     */
    private int mResizeDirection;
    private int mRoundRadius;// Bitmap圆角半径
    private int mRotation;// Bitmap圆角半径

    public PartImageView(@NonNull Context context) {
        this(context, null, 0);
    }


    public PartImageView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PartImageView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PartImageView);
        mResizeDirection = a.getInt(R.styleable.PartImageView_resizeDirection, 0);
        mRoundRadius = a.getInt(R.styleable.PartImageView_roundRadius, 0);
        mRotation = 0;
        a.recycle();

        init();
    }

    private void init() {
        mMatrix = new Matrix();

        mPaint = new Paint();
        mPaint.setAntiAlias(true);

        mPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        if (null != mBitmap) {
            mPaint.setAntiAlias(true);

            int layerId = canvas.saveLayer(getPaddingLeft(), getPaddingTop(), getMeasuredWidth() - getPaddingRight(), getMeasuredHeight() - getPaddingBottom(), mPaint, Canvas.ALL_SAVE_FLAG);
            canvas.drawRoundRect(getPaddingLeft(), getPaddingTop(), getMeasuredWidth() - getPaddingRight(), getMeasuredHeight() - getPaddingBottom(), mRoundRadius, mRoundRadius, mPaint);
            mPaint.setXfermode(mPorterDuffXfermode);
            canvas.drawBitmap(mBitmap, mMatrix, mPaint);
            mPaint.setXfermode(null);
            canvas.restoreToCount(layerId);
        }
        super.onDraw(canvas);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (null != mPartRectF && mBitmap != null && getWidth() != 0 && getHeight() != 0) {
            float ratio = mPartRectF.width() * mBitmap.getWidth() / (mPartRectF.height() * mBitmap.getHeight());
//            int width = View.MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
//            int height = View.MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
            int width = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
            int height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
            if (0 == mResizeDirection) {// 宽度固定，高度可变
                height = (int) (width / ratio);
            } else {// 高度固定，宽度可变
                width = (int) (height * ratio);
            }
            setMeasuredDimension(width + getPaddingLeft() + getPaddingRight(), height + getPaddingTop() + getPaddingBottom());

            //进行缩放操作
            fitBitmapByRectF(false);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    /**
     * 设置/更新 View显示的Bitmap
     * <p>
     * 注意:
     * 1、第一次设置Bitmap时（未设置过显示区域)，默认显示区域为[0, 0, 1.0, 1.0]，
     * View将默认显示Bitmap全貌，View大小与Bitmap大小（可能被缩放）一致
     * <p>
     * 2、非第一次设置Bitmap时（已设置过显示区域），View大小保持不变，显示区域保持不变
     *
     * @param bitmap 要显示的Bitmap
     */
    public void setViewImageBitmap(Bitmap bitmap) {
        mBitmap = bitmap;

        boolean requestLayout = false;
        if (null == mPartRectF) {
            mPartRectF = new RectF(0, 0, 1f, 1f);
            requestLayout = true;
        }
        fitBitmapByRectF(requestLayout);
    }

    /**
     * 设置/更新 View显示Bitmap的指定区域
     * <p>
     * 注意: View会根据rectF的宽高比自动调整
     *
     * @param rectF Bitmap的显示区域，分别为left,top,right,bottom，取值范围为[0, 1.0]
     */
    public void setPartRectF(RectF rectF) {
        mPartRectF = rectF;
        fitBitmapByRectF(true);
    }

    /**
     * 同时设置 View显示的Bitmap和指定区域
     * <p>
     * 注意: View会根据rectF的宽高比自动调整
     *
     * @param bitmap 要显示的Bitmap
     * @param rectF  Bitmap的显示区域，分别为left,top,right,bottom，取值范围为[0, 1.0]
     */
    public void setImageBitmapAndPartRectF(Bitmap bitmap, RectF rectF) {
        mBitmap = bitmap;
        mPartRectF = rectF;
        fitBitmapByRectF(true);
    }

    /**
     * 设置显示Bitmap的圆角半径
     *
     * @param radius
     */
    public void setRoundRadius(int radius) {
        mRoundRadius = radius;
        invalidate();
    }

    /**
     * 设置view的数据
     *
     * @param bitmap
     * @param bean
     * @param resizeDirection
     */
    public void setViewData(Bitmap bitmap, HVPuzzleBean bean, int resizeDirection) {
        mBitmap = bitmap;
        mPartRectF = bean.getRectf();
        mResizeDirection = resizeDirection;
        mRoundRadius = bean.getImgRound();
        mRotation = bean.getRotation();
        fitBitmapByRectF(true);
    }

    /**
     * 缩放&移动Bitmap，调整View大小，使得View仅显示指定的显示区域
     *
     * @param requestLayout true，改变View大小且重绘View；false，仅重绘View
     */
    private void fitBitmapByRectF(boolean requestLayout) {
        Log.e("缩放", "调整View大小");
        post(new Runnable() {
            @Override
            public void run() {
                final float width = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
                final float height = getMeasuredHeight() - getPaddingBottom() - getPaddingTop();
                final float scale = width / (mPartRectF.width() * mBitmap.getWidth());
                final float dx = mPartRectF.left * mBitmap.getWidth() * scale;
                final float dy = mPartRectF.top * mBitmap.getHeight() * scale;
                //缩放
                mMatrix.setScale(scale, scale);
                //平移
                mMatrix.postTranslate(-dx + getPaddingLeft(), -dy + getPaddingTop());
                if (requestLayout) {// 重新布局，调整View大小
                    requestLayout();
                } else {// 仅刷新绘制，不改变View大小
                    invalidate();
                }
            }
        });
    }

    public Bitmap getDrawingBitmap(
            int paddingLeft,
            int paddingTop,
            int paddingRight,
            int paddingBottom,
            int roundRadius,
            int widthOrHeight,
            int direction,
            Bitmap bitmap,
            RectF rectF) {

        // 最终生成Bitmap的宽高
        int width, height;

        // 图片显示区域的宽高比
        float ratio = rectF.width() * bitmap.getWidth() / (rectF.height() * bitmap.getHeight());

        // 计算图片宽高
        if (0 == direction) {// 竖直方向
            width = widthOrHeight;
            height = (int) (width / ratio);
        } else {// 水平方向
            height = widthOrHeight;
            width = (int) (height * ratio);
        }

        // 加上边距
        width += paddingLeft + paddingRight;
        height += paddingTop + paddingBottom;

        // 使用原图进行绘制，避免重复创建新的Bitmap，降低OOM概率
        final float widthReal = width - paddingLeft - paddingRight;
        final float scale = widthReal / (rectF.width() * bitmap.getWidth());
        final float dx = rectF.left * bitmap.getWidth() * scale;
        final float dy = rectF.top * bitmap.getHeight() * scale;

        Matrix matrix = new Matrix();
        matrix.setScale(scale, scale);
        matrix.postTranslate(-dx + paddingLeft, -dy + paddingTop);

        // 绘制开始
        Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(result);
//        canvas.drawColor(Color.GREEN);
        Paint paint = new Paint();
        paint.setAntiAlias(true);

        int layerId = canvas.saveLayer(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom, paint, Canvas.ALL_SAVE_FLAG);
        canvas.drawRoundRect(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom, roundRadius, roundRadius, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));// 处理圆角
        canvas.drawBitmap(bitmap, matrix, paint);
        paint.setXfermode(null);
        canvas.restoreToCount(layerId);

        return result;
    }
}
